package ink.xiaobaibai.controller.monthly;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ink.xiaobaibai.bo.UpdateMonAdminUserIdBo;
import ink.xiaobaibai.common.*;
import ink.xiaobaibai.entity.*;
import ink.xiaobaibai.enumOxy.DepositStatus;
import ink.xiaobaibai.enumOxy.MonthlyfeeOrderStatus;
import ink.xiaobaibai.enumOxy.ReturnDepositStatus;
import ink.xiaobaibai.multipleClick.ForbidMultipleClick;
import ink.xiaobaibai.response.ResponseFormat;
import ink.xiaobaibai.service.*;
import ink.xiaobaibai.service.monthly.IDelayTaskCommonService;
import ink.xiaobaibai.serviceOxy.IRedisUtils;
import ink.xiaobaibai.serviceOxy.ISmsService;
import ink.xiaobaibai.serviceOxy.pay.IPayService;
import ink.xiaobaibai.serviceOxy.pay.impl.PayServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @description: 月费接口
 * @author: 小白白
 * @create: 2021-05-22
 **/

@Api(tags = "月费接口")
@RestController
@RequestMapping("/monthlyfee")
@Slf4j
public class MonthlyfeeController {

    @Autowired
    private IPayService payService;

    @Autowired
    private IMonthlyfeeDeviceService monthlyfeeDeviceService;

    @Autowired
    private IMonthlyfeeDepositService monthlyfeeDepositService;

    @Autowired
    private IMonthlyfeeOrderService monthlyfeeOrderService;

    @Autowired
    private IMonthlyRefundDepositService refundDepositService;

    @Autowired
    private IAdminUserService adminUserService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ICouponUserService couponUserService;

    @Autowired
    private IDelayTaskCommonService delayTaskCommonService;

    @Autowired
    private ICouponCodeService couponCodeService;

    @Autowired
    private IRedisUtils redisUtils;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private ILogisticsService logisticsService;

    @Autowired
    private IMonthlyUserDeviceService userDeviceService;

    /**
     * 获取押金费用
     */
    @GetMapping("/deposit-amount")
    @ApiOperation("押金费用")
    public ResponseFormat depositAmount() {
        return ResponseFormat.success(SettingCommon.getDepositKey());
    }

    /**
     * 缴纳押金
     */
    @PostMapping("/payment-deposit")
    @ApiOperation("缴纳押金,返回下单信息(需要客户填写信息)")
    @ForbidMultipleClick(durationSecondsTime = 10, msg = "10秒后再试")
    public ResponseFormat paymentDeposit(@RequestBody @Validated ClientInfo clientInfo) {
        if (clientInfo.getPhone() == null || clientInfo.getPhone().length() != 11) {
            return ResponseFormat.fail("请填写正确的手机号");
        }
        if (clientInfo.getAdminUserId() == null) {
            clientInfo.setAdminUserId(Common.DEFAULT_ADMIN_USER_ID);
        }
        Integer userId = MySecurity.getUserId();
        this.stringRedisTemplate.opsForValue().set(Common.DEPOSIT_PRE + userId, JSON.toJSONString(clientInfo), 30, TimeUnit.MINUTES);
        WxPayment wxPayment = this.payService.depositPay(SettingCommon.getDepositKey(), userId);
        return ResponseFormat.success(wxPayment);
    }

    /**
     * 查看自己的押金情况
     */
    @GetMapping("/deposit-detailed")
    @ApiOperation("查询自己的押金明细(返回的是自己的押金集合)")
    public ResponseFormat depositDetailed() {
        QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
        q1.eq("user_id", MySecurity.getUserId());
        List<MonthlyfeeDeposit> list = this.monthlyfeeDepositService.list(q1);
        list.sort((o1, o2) -> (int) (o2.getCreateTime().getTime() - o1.getCreateTime().getTime()));
        return ResponseFormat.success(list);
    }

    /**
     * 查询月费金额
     */
    @GetMapping("/monthlyfee-amount")
    @ApiOperation("查询月费金额")
    public ResponseFormat monthlyfeeAmount() {
        return ResponseFormat.success(SettingCommon.getMonthlyFee());
    }

    /**
     * 新开通月费机器
     */
    @PostMapping("/new-monthlyfee")
    @ApiOperation("新开通月费||扫码获取adminUserId 或者 输入即可")
    @ForbidMultipleClick(durationSecondsTime = 15, msg = "15秒后再试")
    public ResponseFormat newMonthlyfee(@RequestBody @Validated NewMonthlyBo newMonthlyBo) {

        if (newMonthlyBo.getCouponId() != null && newMonthlyBo.getCouponCode() != null) {
            return ResponseFormat.fail("不能同时使用优惠券和优惠码");
        }

        Integer adminUserId = newMonthlyBo.getAdminUserId();
        Integer userId = MySecurity.getUserId();

        //对应用户是否存在
        QueryWrapper<AdminUser> q2 = new QueryWrapper<>();
        q2.eq("id", adminUserId);
        if (this.adminUserService.count(q2) == 0) {
            return ResponseFormat.fail("当前管理员id不存在");
        }

        MonthlyfeeDeposit deposit = null;
        boolean flag = this.adminUserService.isSupplierAdminUser(adminUserId);
        // 向非供应商开通,需要缴纳押金
        if (!flag) {
            QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
            q1.eq("user_id", userId);
            //要有空闲的押金才可以开通月费机器
            q1.eq("status", DepositStatus.FREE.getStatus());
            q1.last("limit 1");
            deposit = this.monthlyfeeDepositService.getOne(q1);
            if (deposit == null) {
                return ResponseFormat.fail("当前有效押金不足,不可开通月费");
            }
            Boolean hasKey = this.stringRedisTemplate.hasKey(PayServiceImpl.ORDER_DEP + deposit.getOrderId());
            if (hasKey) {
                return ResponseFormat.fail("操作过快,请稍后再试");
            }
            // 打上押金标识
            this.stringRedisTemplate.opsForValue().set(PayServiceImpl.ORDER_DEP + deposit.getOrderId(), "1", 20, TimeUnit.SECONDS);
        }

        this.monthlyfeeOrderService.setNewMonthlyInfo(newMonthlyBo, userId);
        // 去查询对应的优惠券
        BigDecimal amount = SettingCommon.getMonthlyFee();
        CouponUserIdAndPrice couponUserIdAndPrice = null;
        if (newMonthlyBo.getCouponId() != null || newMonthlyBo.getCouponCode() != null) {
            couponUserIdAndPrice = this.checkCoupon(newMonthlyBo.getCouponId(), newMonthlyBo.getCouponCode(), amount);
            amount = couponUserIdAndPrice.price;
        }

        // 一个月份*count不就行了
        BigDecimal countBigDecimal = new BigDecimal(newMonthlyBo.getCount());
        amount = amount.multiply(countBigDecimal);

        //新开通,无机器id
        WxPayment wxPayment = this.payService.monthlyNewPay(amount, userId, adminUserId);

        String orderId = PayServiceImpl.getOrderId();

        // 非供应商要检车押金
        if (!flag) {
            this.stringRedisTemplate.opsForValue().set(PayServiceImpl.ORDER_DEP + orderId, deposit.getOrderId(), 15, TimeUnit.MINUTES);
        } else {
            this.stringRedisTemplate.delete(PayServiceImpl.ORDER_DEP + orderId);
        }

        this.stringRedisTemplate.opsForValue().set(orderId, String.valueOf(newMonthlyBo.getCount()), 15, TimeUnit.MINUTES);

        if (couponUserIdAndPrice != null && couponUserIdAndPrice.couponId != null) {
            // 使用了优惠券
//            delayTaskCommonService.couponAddCheckStatus(couponUserIdAndPrice.couponId, couponUserIdAndPrice.couponUserId, orderId);
            this.redisUtils.saveCoupon(orderId, couponUserIdAndPrice.couponId);
        }
        if (couponUserIdAndPrice != null && couponUserIdAndPrice.code != null) {
            // 使用了优惠码
//            delayTaskCommonService.couponCodeAddCheckStatus(newMonthlyBo.getCouponCode(), orderId);
            this.redisUtils.saveCouponCode(orderId, couponUserIdAndPrice.code);
        }

        return ResponseFormat.success(wxPayment);
    }

    /**
     * 修改包月订单的adminUserId
     * 只能在未分配机器状态时,才可以修改;
     * 传入两个参数: admin_user_id 和 order_id
     */
    @PutMapping("/update-mon-admin-user")
    @ApiOperation("修改包月订单的adminUserId")
    @ForbidMultipleClick(durationSecondsTime = 8, msg = "8秒后再试")
    public ResponseFormat updateMonAdminUser(@RequestBody @Validated UpdateMonAdminUserIdBo updateMonAdminUserIdBo) {
        Integer adminUserId = updateMonAdminUserIdBo.getAdminUserId();
        String orderId = updateMonAdminUserIdBo.getOrderId();
        QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
        q1.select("user_id", "admin_user_id", "status");
        q1.eq("order_id", orderId);
        MonthlyfeeOrder monthlyfeeOrder = this.monthlyfeeOrderService.getOne(q1);
        if (monthlyfeeOrder == null || !monthlyfeeOrder.getUserId().equals(MySecurity.getUserId())) {
            return ResponseFormat.fail("对应订单不存在");
        }
        if (monthlyfeeOrder.getAdminUserId().equals(adminUserId)) {
            return ResponseFormat.fail("不可重复修改");
        }
        // 是否为 供应商 <--> 业务员间切换
        boolean flag1 = this.adminUserService.isSupplierAdminUser(adminUserId);
        boolean flag2 = this.adminUserService.isSupplierAdminUser(monthlyfeeOrder.getAdminUserId());
        if (flag1 != flag2) {
            return ResponseFormat.fail("两负责人角色身份不同,切换失败");
        }
        if (!monthlyfeeOrder.getStatus().equals(MonthlyfeeOrderStatus.UNALLOCATED.getStatus())) {
            return ResponseFormat.fail("当前机器已分配,操作失败");
        }
        QueryWrapper<AdminUser> q2 = new QueryWrapper<>();
        q2.eq("id", updateMonAdminUserIdBo.getAdminUserId());
        if (this.adminUserService.count(q2) == 0) {
            return ResponseFormat.fail("当前id不存在");
        }
        UpdateWrapper<MonthlyfeeOrder> u1 = new UpdateWrapper<>();
        u1.set("admin_user_id", adminUserId);
        u1.set("admin_dep_id", this.adminUserService.getDepId(adminUserId));
        u1.eq("order_id", orderId);
        u1.eq("status", MonthlyfeeOrderStatus.UNALLOCATED.getStatus());
        if (!this.monthlyfeeOrderService.update(u1)) {
            //并发情况: 已经分配了
            return ResponseFormat.fail("修改失败");
        }
        return ResponseFormat.success();
    }


    /**
     * 续约对应的月费机器
     */
    @PostMapping("/renewal-monthlyfee")
    @ApiOperation("续约月费")
    @ForbidMultipleClick(durationSecondsTime = 30, key = "#xuMonthly.deviceId", msg = "请勿多次点击", prefixUserId = true)
    public ResponseFormat renewalMonthlyfee(@RequestBody @Validated XuMonthly xuMonthly) {

        if (xuMonthly.getCouponId() != null && xuMonthly.getCouponCode() != null) {
            return ResponseFormat.fail("不能同时使用优惠券和优惠码");
        }

        Integer userId = MySecurity.getUserId();

        QueryWrapper<MonthlyfeeDevice> q0 = new QueryWrapper<>();
        q0.select("admin_user_id");
        q0.eq("id", xuMonthly.getDeviceId());
        MonthlyfeeDevice monthlyfeeDevice = this.monthlyfeeDeviceService.getOne(q0);
        if (monthlyfeeDevice == null) {
            return ResponseFormat.fail("当前机器不存在");
        }
        if (!this.adminUserService.isSupplierAdminUser(monthlyfeeDevice.getAdminUserId())) {
            //当前押金表: 占用中&&机器id正确
            QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
            q1.eq("user_id", userId);
            q1.eq("device_id", xuMonthly.getDeviceId());
            MonthlyfeeDeposit monthlyfeeDeposit = this.monthlyfeeDepositService.getOne(q1);
            if (monthlyfeeDeposit == null) {
                return ResponseFormat.fail("此机器未被您占用");
            }
            if (!monthlyfeeDeposit.getStatus().equals(DepositStatus.OCCUPIED.getStatus())) {
                //押金非占用中状态
                return ResponseFormat.fail("押金状态错误,不可续约");
            }
        } else {
            // CHENG12345678
            // 供应商层 此机器是否被自己占用了
            QueryWrapper<MonthlyUserDevice> q1 = new QueryWrapper<>();
            q1.eq("user_id", userId);
            q1.eq("device_id", xuMonthly.getDeviceId());
            if (this.userDeviceService.count(q1) == 0) {
                return ResponseFormat.fail("此机器未被您占用");
            }
        }


        // 去查询对应的优惠券
        BigDecimal amount = SettingCommon.getMonthlyFee();
        CouponUserIdAndPrice couponUserIdAndPrice = null;
        if (xuMonthly.getCouponId() != null) {
            couponUserIdAndPrice = this.checkCoupon(xuMonthly.getCouponId(), xuMonthly.getCouponCode(), amount);
        }

        BigDecimal countBigDecimal = new BigDecimal(xuMonthly.getCount());
        amount = amount.multiply(countBigDecimal);

        //当前可以进行续约
        WxPayment wxPayment = this.payService.monthlyContinuePay(amount, userId, xuMonthly.getDeviceId());
        String orderId = PayServiceImpl.getOrderId();
        this.stringRedisTemplate.opsForValue().set(orderId, String.valueOf(xuMonthly.getCount()), 15, TimeUnit.MINUTES);

        if (couponUserIdAndPrice != null && couponUserIdAndPrice.couponId != null) {
            // 使用了优惠券
//            delayTaskCommonService.couponAddCheckStatus(couponUserIdAndPrice.couponId, couponUserIdAndPrice.couponUserId, orderId);
            this.redisUtils.saveCoupon(orderId, couponUserIdAndPrice.couponId);
        }
        if (couponUserIdAndPrice != null && couponUserIdAndPrice.code != null) {
            // 使用了优惠码
//            delayTaskCommonService.couponCodeAddCheckStatus(xuMonthly.getCouponCode(), orderId);
            this.redisUtils.saveCouponCode(orderId, couponUserIdAndPrice.code);
        }
        return ResponseFormat.success(wxPayment);
    }

    /**
     * 申请退还押金
     * 传入的是押金id
     */
    @PostMapping("/apply-return-deposit")
    @ApiOperation("申请退还押金")
    @ForbidMultipleClick(key = "#depositId", msg = "订单冷却中")
    public ResponseFormat returnDeposit(@RequestBody String depositId) {
        Integer userId = MySecurity.getUserId();
        QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
        q1.eq("order_id", depositId);
        //防止横向
        q1.eq("user_id", userId);
        MonthlyfeeDeposit monthlyfeeDeposit = this.monthlyfeeDepositService.getOne(q1);
        if (monthlyfeeDeposit == null) {
            return ResponseFormat.fail("无押金可申请");
        }
        /**
         * 没有绑定月费,那么可以直接退,如果绑定了月费,再退款就需要流程了
         */
        if (monthlyfeeDeposit.getStatus().equals(DepositStatus.FREE.getStatus())) {
            this.payService.refundByDepositIdWhitNoMon(depositId);
            return ResponseFormat.success();
        }
        if (monthlyfeeDeposit.getStatus().equals(DepositStatus.APPLYING.getStatus())) {
            return ResponseFormat.fail("已在申请中");
        }
        /**
         * 已经绑定了月费,但订单未在使用中或已过期,那么也不可退,必须在激活后的状态才可以退款
         */
        Integer deviceId = monthlyfeeDeposit.getDeviceId();
        QueryWrapper<MonthlyfeeOrder> q2 = new QueryWrapper<>();
        q1.select("order_id", "logistics_id");
        q2.eq("user_id", userId);
        q2.eq("device_id", deviceId);
        q2.in("status", MonthlyfeeOrderStatus.INUSE.getStatus(), MonthlyfeeOrderStatus.EXPIRED.getStatus());
        MonthlyfeeOrder order = this.monthlyfeeOrderService.getOne(q2);
        if (order == null) {
            return ResponseFormat.fail("机器审核流程未结束,不可退款");
        }
        //修改押金状态
        UpdateWrapper<MonthlyfeeDeposit> u1 = new UpdateWrapper<>();
        u1.set("status", DepositStatus.APPLYING.getStatus());
        u1.eq("order_id", depositId);
        this.monthlyfeeDepositService.update(u1);
        //修改订单表状态 去查看续费的地方,需要查看订单状态为使用中或者过期,才可以续费->已验证上方的押金表
        order.setStatus(MonthlyfeeOrderStatus.APDEPOSIT.getStatus());
        this.monthlyfeeOrderService.updateById(order);
        //创建退款表
        MonthlyRefundDeposit monthlyRefundDeposit =
                new MonthlyRefundDeposit(order.getOrderId(), depositId, order.getLogisticsId(), null, ReturnDepositStatus.ONE.getStatus());
        this.refundDepositService.save(monthlyRefundDeposit);
        this.smsService.returnDeposit(depositId);
        return ResponseFormat.success();
    }

    /**
     * 撤销申请退还押金
     */
    @PostMapping("/cancel-apply-return-deposit")
    @ApiOperation("撤销退还押金")
    @ForbidMultipleClick(key = "#depositId", msg = "订单冷却中")
    public ResponseFormat cancelApplyReturnDeposit(@RequestBody String depositId) {
        Integer userId = MySecurity.getUserId();
        QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
        q1.eq("order_id", depositId);
        q1.eq("user_id", userId);
        MonthlyfeeDeposit monthlyfeeDeposit = this.monthlyfeeDepositService.getOne(q1);
        if (monthlyfeeDeposit == null) {
            return ResponseFormat.fail("无申请可撤销");
        }
        if (!monthlyfeeDeposit.getStatus().equals(DepositStatus.APPLYING.getStatus())) {
            //非申请撤销状态
            return ResponseFormat.fail("非申请撤销状态");
        }
        //已经退款完成,则不可重复申请
        QueryWrapper<MonthlyRefundDeposit> q3 = new QueryWrapper<>();
        q3.eq("deposit_id", depositId);
        q3.eq("status", ReturnDepositStatus.OK.getStatus());
        if (this.refundDepositService.count(q3) == 1) {
            return ResponseFormat.success("已经退款完成,不可重复申请");
        }
        //修改订单状态
        Integer deviceId = monthlyfeeDeposit.getDeviceId();
        QueryWrapper<MonthlyfeeOrder> q2 = new QueryWrapper<>();
        q2.select("order_id", "status", "expire_time");
        q2.eq("user_id", userId);
        q2.eq("device_id", deviceId);
        q2.eq("status", MonthlyfeeOrderStatus.APDEPOSIT.getStatus());
        MonthlyfeeOrder order = this.monthlyfeeOrderService.getOne(q2);
        if (order.getExpireTime().getTime() < (new Date()).getTime()) {
            //过期了
            order.setStatus(MonthlyfeeOrderStatus.EXPIRED.getStatus());
        } else {
            //没过期
            order.setStatus(MonthlyfeeOrderStatus.INUSE.getStatus());
        }
        this.monthlyfeeOrderService.updateById(order);
        //修改退款押金状
//        UpdateWrapper<MonthlyRefundDeposit> u0=new UpdateWrapper<>();
//        u0.set("status",ReturnDepositStatus.CANCEL.getStatus());
//        //可修改所有,之前只要存在,那么就是已经取消的
//        u0.eq("deposit_id",depositId);
//        refundDepositService.update(u0);
        //直接删除退款押金记录得了,不用修改状态
        QueryWrapper<MonthlyRefundDeposit> q4 = new QueryWrapper<>();
        q4.eq("deposit_id", depositId);
        this.refundDepositService.remove(q4);
        //修改押金状态
        UpdateWrapper<MonthlyfeeDeposit> u1 = new UpdateWrapper<>();
        u1.eq("order_id", depositId);
        if (monthlyfeeDeposit.getDeviceId() != null) {
            //被占用了,那么先前就是占用状态
            u1.set("status", DepositStatus.OCCUPIED.getStatus());
        } else {
            //先前就是空闲状态
            log.error("这一步不该走到,因为空闲状态会直接退款,无需审核");
            u1.set("status", DepositStatus.FREE.getStatus());
        }
        this.monthlyfeeDepositService.update(u1);
        return ResponseFormat.success();
    }

    @GetMapping("/monthlyfee-order-list")
    @ApiOperation("查询自己的历史月费订单|expire_time是本次订单支付后的下一次过期时间(续约/新开通)")
    public ResponseFormat monthlyfeeOrderList(@RequestParam(value = "pageNum", defaultValue = "1", required = false) Integer pageNum,
                                              @RequestParam(value = "pageSize", defaultValue = "10", required = false) Integer pageSize) {
        Integer userId = MySecurity.getUserId();
        QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
        q1.eq("user_id", userId);
        q1.orderByDesc("create_time");
        //total为0无影响
        Page<MonthlyfeeOrder> page = this.monthlyfeeOrderService.page(new Page<>(pageNum, pageSize, 0, false), q1);
        return ResponseFormat.success(page.getRecords());
    }

    /**
     * 月费订单item
     */
    @GetMapping("/item")
    @ApiOperation("月费订单详细 | 订单详细+机器型号+客户信息")
    public ResponseFormat item(@RequestParam("orderId") String orderId) {
        MonthlyfeeOrder order = this.monthlyfeeOrderService.getById(orderId);
        Integer logisticsId = order.getLogisticsId();
        Logistics logistics = this.logisticsService.getById(logisticsId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("order", order);
        jsonObject.put("logistics", logistics);
        return ResponseFormat.success(jsonObject);
    }

    private CouponUserIdAndPrice checkCoupon(Integer couponId, String code, BigDecimal amount) {
        if (couponId != null) {
            //拥有优惠券,记得将优惠券锁定3分钟
            //是否拥有此优惠券
            QueryWrapper<CouponUser> q1 = new QueryWrapper<>();
            q1.select("id", "expires_time", "status");
            q1.eq("coupon_id", couponId);
            q1.eq("user_id", MySecurity.getUserId());
            CouponUser couponUser = this.couponUserService.getOne(q1);
            //优惠券不可用,直接原价
            if (!couponUser.getStatus().equals(CouponStatus.CAN_USE.getStatus()) || couponUser.getExpiresTime().getTime() < System.currentTimeMillis()) {
                return new CouponUserIdAndPrice(amount);
            }
            //一层优惠券可用,再查询是否停用和包月业务
            QueryWrapper<Coupon> q2 = new QueryWrapper<>();
            q2.select("percentage", "stop_use");
            q2.eq("id", couponId);
            q2.eq("type", Common.CouponType.monthlyCoupon);
            Coupon coupon = this.couponService.getOne(q2);
            if (coupon == null) {
                // 当前优惠券非定点业务的
                return new CouponUserIdAndPrice(amount);
            }
            if (coupon.getStopUse()) {
                //当前优惠券已经停用
                return new CouponUserIdAndPrice(amount);
            }
            //可用
            BigDecimal percentage = new BigDecimal(String.valueOf(((double) coupon.getPercentage() / 100d)));
            //切记一定使用double,然后将double转string,再做运算
            amount = new BigDecimal(String.valueOf(amount.doubleValue()));
            amount = amount.multiply(percentage);
            couponUser.setStatus(CouponStatus.LOCK.getStatus());
//            couponUserService.updateById(couponUser);
            return new CouponUserIdAndPrice(amount, couponId, couponUser.getId());
        } else {
            CouponCode couponCode = this.couponCodeService.validCouponCode(code, Common.CouponType.monthlyCoupon);
            if (couponCode == null) {
                return new CouponUserIdAndPrice(amount);
            }
            // 开始使用优惠券
            Integer couponPercentage = couponCode.getPercentage();
            BigDecimal percentage = new BigDecimal(String.valueOf(((double) couponPercentage / 100d)));
            amount = new BigDecimal(String.valueOf(amount.doubleValue()));
            amount = amount.multiply(percentage);
            CouponUserIdAndPrice couponUserIdAndPrice = new CouponUserIdAndPrice(amount);
            couponUserIdAndPrice.setCode(code);
            return couponUserIdAndPrice;
        }
    }

    private class CouponUserIdAndPrice {
        private BigDecimal price;
        private Integer couponId;
        private Integer couponUserId;
        private String code;

        public CouponUserIdAndPrice(BigDecimal price, Integer couponId, Integer couponUserId) {
            this.price = price;
            this.couponId = couponId;
            this.couponUserId = couponUserId;
        }

        public CouponUserIdAndPrice(BigDecimal price) {
            this.price = price;
        }

        public String getCode() {
            return this.code;
        }

        public void setCode(String code) {
            this.code = code;
        }
    }

}
